/**********************************************************************//**
 @file mesh.hpp 
 @brief Contains methods for manipulating a 2D triangular mesh
 @author Ricardo C. Marques    <rmarques@inf.puc-rio.br>
 @author Antonio S. Nascimento <asergio@tecgraf.puc-rio.br>
 @author Marcos V. M. da Silva <mvmsilva@tecgraf.puc-rio.br>
 @version 0.0.1
 @date 07/11/2012
**************************************************************************/
#ifndef _MESH_HPP
#define _MESH_HPP

#include <vector>
using namespace std;

#include "primitives.hpp"

class Mesh
{
    public:
        Mesh( int NumVertices, Point3D* Vertices, 
              int NumTri, int* Triangles); // all tri must be oriented counterclockwise
        virtual ~Mesh();

    // Inquire Methods
    public:

        // Given a Half Edge
        bool isValidHE(int he); // checks if this half edge exists
        int  GetNextHE(int he); // returns the next half edge
        int  GetPrevHE(int he); // returns the previous half edge
        int  GetOppHE (int he); // returns the opposite half edge (mate)
        int  GetHETri (int he); // returns the triangle which contains this half edge
        void GetHEVertices(int he, int* v0, int* v1); // returns the 2 vertices of this half edge
        int  GetHEOppVertex(int he); // return the vertex opposite to this edge

        // Given a Triangle
        bool isValidTri(int tri); // checks if this triangle exists
        void GetTriHalfEdges(int tri, int* he1, int* he2, int* he3); // returns the 3 half edges of this triangle
        void GetTriVertices (int tri, int* v0, int* v1, int* v2);    // returns the 3 vertices of this triangle
        void GetTriAdjTri(int tri, int* tri0, int*tri1, int* tri2);  // returns 3 triangles adjacent to this triangle
        //void Get

        // Given a Vertex
        bool isValidVertex (int v); // checks if this vertex exists
        void GetVertexCoord(int v, Point3D* coord); // return coords of a this vertex

    // Mesh Operators
    public:
        void Split(Point3D p);
        //void Weld(int he);
        //void Merge(.....);
        //void Glue(int he1, int he2);
        //void Zip(int he1, int he2);
        //void ....
        bool isOptimal(int he); 
        void Flip(int he);
    private:
        int  FindPoint(Point3D P, int* index);
        void SplitHE (int he , Point3D P);
        void SplitInnerHE  (int he , Point3D P);
        void SplitBorderHE (int he , Point3D P);
        void SplitTri(int tri, Point3D P);

    // Private Variables
    private:
        int m_NumVertices;
        vector<Point3D> m_Vertices;

        int m_NumHalfEdges;
        vector<int> m_HESourceVtx;
        vector<int> m_OppositeHE;

        int m_NumTriangles;
};

#endif